/*
 * @Author: hongbin
 * @Date: 2022-07-25 12:03:41
 * @LastEditors: hongbin
 * @LastEditTime: 2022-09-07 16:00:35
 * @Description:电脑模型的交互 屏幕交互
 */
import THREE from "../../";
import { getSize } from "../../helper";

const { Mesh, MeshBasicMaterial, PlaneGeometry, Texture } = THREE;

interface InterPointProps {
    ctx: CanvasRenderingContext2D;
    inputs: string[];
    lineWidth: number;
    lineHength: number;
    delay: number;
    padding: { top: number; bottom: number; left: number; right: number };
}

class InterPoint {
    props!: InterPointProps;
    timer!: NodeJS.Timeout;
    prevInterPoint: [number, number] = [0, 0];
    lineColor = "#51f";
    update: () => void = () => {};
    constructor(props: InterPointProps) {
        this.props = props;
        this.stopListener();
    }
    registerUpdate(update: () => void) {
        this.update = update;
    }
    /**
     * 更新线条颜色
     */
    setLineColor(lineColor: string) {
        this.lineColor = lineColor;
    }

    /**
     * 画垂直的直线
     */
    drawVerticalLine = (x: number, y: any, height: number) => {
        const { ctx, lineWidth } = this.props;
        ctx.beginPath();
        ctx.lineWidth = lineWidth;
        ctx.moveTo(x, y);
        ctx.lineTo(x, y + height);
        ctx.strokeStyle = this.lineColor;
        ctx.stroke();
        ctx.closePath();
    };
    /**
     * 更新插入点坐标
     */
    updateInterPoint() {
        const { ctx, inputs, lineHength, padding } = this.props;
        const x = ctx.measureText(inputs[inputs.length - 1]).width + 20 + padding.left;
        const y = (inputs.length - 1) * lineHength + padding.top;
        this.prevInterPoint = [x, y];
    }
    /**
     * 清除插入点 其实是覆盖 防止扣出一个"窟窿"
     */
    clear() {
        const { ctx, lineWidth, lineHength } = this.props;
        const point: [number, number, number, number] = [
            this.prevInterPoint[0] - lineWidth / 2 - 1,
            this.prevInterPoint[1],
            this.prevInterPoint[0] + lineWidth,
            this.prevInterPoint[1] + lineHength,
        ];
        ctx.fillStyle = "#fff";
        ctx.fillRect(...point);
        // this.ctx.clearRect(
        //     this.prevInterPoint[0] - this.lineWidth / 2 - 1,
        //     this.prevInterPoint[1],
        //     this.prevInterPoint[0] + this.lineWidth,
        //     this.prevInterPoint[1] + this.lineHength
        // );
    }

    /**
     * 循环 绘制插入点 添加闪烁行为
     * TODO 当按下esc时 定制计时器 可以设置一个方法 或者监听 或者什么方式 要按需渲染
     */
    drawInsetPoint(state: boolean) {
        const { delay, lineHength } = this.props;
        if (state) {
            this.updateInterPoint();
            this.drawVerticalLine(...this.prevInterPoint, lineHength);
        } else {
            this.clear();
        }
        this.update && this.update();

        this.timer = setTimeout(() => {
            this.drawInsetPoint(!state);
        }, delay);
    }
    /**
     * 立刻更新
     */
    immediatelyUpdate() {
        this.stop();
        this.drawInsetPoint(true);
    }

    start() {
        this.drawInsetPoint(true);
    }
    stop() {
        clearTimeout(this.timer);
    }

    stopListener() {
        window.addEventListener("stoprender", () => {
            this.stop();
        });
    }
}

export function ComputerScreenController() {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
    let isOff = true; //当前是否为关机状态
    const fontSize = 100;
    const material = new MeshBasicMaterial({});
    const inputs = [""];
    const padding = { top: fontSize, bottom: fontSize, left: 50, right: 50 };
    let insertPoint: InterPoint;
    let navImg: HTMLImageElement;

    /**
     * 原来的模型有缩放等效果不适合直接使用 使用一个相同大小的几何覆盖将其覆盖
     */
    function init(screenTemp: THREE.Object3D) {
        const { x, y } = getSize(screenTemp);
        const geometry = new PlaneGeometry(x, y, 1, 1);
        const screen = new Mesh(geometry, material);
        screen.position.set(2, 65, -42.4);
        // guiTestPosition(screen);
        screenTemp.parent!.add(screen);

        //宽高根据模型宽高比设置
        canvas.width = x * 30;
        canvas.height = y * 30;

        insertPoint = new InterPoint({ ctx, inputs, lineWidth: 20, lineHength: fontSize, delay: 500, padding });
        insertPoint.registerUpdate(update);
        // navImg = new Image();
        // //设置图片地址
        // navImg.src = navImgPath;
        // // navImg.onload = () => {
        // //     // ctx.drawImage(navImg, 0, 0, 100, 100);
        // //     drawText("", padding, padding, 120);
        // //     update();
        // //     window.render();
        // // };
        // drawBg();
        // start();
        material.map = new Texture(canvas);
    }
    /**
     * 开机
     */
    function turnOn() {
        drawBg();
        insertPoint.start();
        update();
        isOff = false;
    }
    /**
     * 关机
     */
    function turnOff() {
        //清空数组
        // inputs.length = 0;
        inputs.splice(0, inputs.length);
        inputs.push("");
        /**
         * 插入点隐藏
         */
        insertPoint.stop();
        //重置画布
        ctx.fillStyle = "#000000";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        update();
        isOff = true;
    }

    function drawBg() {
        ctx.fillStyle = "#fff";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        const gnt = ctx.createLinearGradient(0, 0, canvas.width, 0);
        gnt.addColorStop(0, "#cccccc");
        gnt.addColorStop(0.5, "#888888");
        gnt.addColorStop(1, "#cccccc");
        ctx.fillStyle = gnt;
        //绘制一个矩形
        ctx.fillRect(0, 0, canvas.width, fontSize);
        //系统图标
        drawText(" 🛹", fontSize / 2, 0, fontSize);
        drawText("             桌面    文件    窗口    帮助", fontSize / 2, fontSize / 10, fontSize * 0.7);
    }

    const drawText = (text: string, x: number, y: number, size: number = fontSize) => {
        ctx.beginPath();
        ctx.font = `${size}px 微软雅黑`;
        ctx.fillStyle = "#000";
        ctx.textBaseline = "top";
        ctx.fillText(text, x, y);
        ctx.closePath();
    };

    function render() {
        //清空画布
        // ctx.clearRect(0, 0, canvas.width, canvas.height);
        //不重置导航栏
        ctx.clearRect(padding.left, padding.top, canvas.width, canvas.height);
        drawBg();
        //绘制文字
        inputs.forEach((input, index) => {
            drawText(input, padding.left, index * fontSize + padding.top);
        });
        insertPoint.immediatelyUpdate();
    }

    function handleDrawText(text: string) {
        const { length } = inputs;
        const tempStr = inputs[length - 1] + text;
        const tempWidth = ctx.measureText(tempStr).width;
        //宽度已经满了 需要开下一行输入
        if (tempWidth > canvas.width - padding.left - padding.right) {
            //段落高度不能超过屏幕高度
            length * fontSize + fontSize < canvas.height - padding.top - padding.bottom &&
                //开启新的一行
                inputs.push(text);
        } else inputs[length - 1] += text;
        render();
    }

    function delText() {
        const last = inputs.length - 1;
        if (inputs[last].length) {
            inputs[last] = inputs[last].substring(0, inputs[last].length - 1);
        } else inputs.pop();
        render();
    }

    function input(text: string) {
        //关机状态不执行操作
        if (isOff) return;
        if (text === "delete") {
            delText();
        } else handleDrawText(text);
    }

    function update() {
        material.map && (material.map.needsUpdate = true);
    }

    return {
        init,
        turnOn,
        turnOff,
        input,
    };
}
